package xyz.whiteblue.core;


import xyz.whiteblue.beetl.BeetlRenderFactory;
import xyz.whiteblue.controller.ActionFactory;
import xyz.whiteblue.controller.Controller;
import xyz.whiteblue.interceptor.Interceptor;
import xyz.whiteblue.render.RenderFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by WhiteBlue on 15/6/2.
 */
public class CoreFilter implements Filter {
    public static final String slash = "/";//用于url分割
    private Map<String, Class> controllerMap;
    private Map<Class, Map<String, Action>> methodMap;
    private List<Interceptor> globalInterceptors;


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Config config = Config.getConfig();
        config.init(filterConfig.getServletContext(), filterConfig);

        globalInterceptors = new ArrayList<Interceptor>();

        if (!initMaps())
            throw new RuntimeException("Path init Failed !!!!");

        if (!initRender())
            throw new RuntimeException("Render init Failed !!!!");

        if (Config.getConfigClass() != null) {
            if (!initMore(Config.getConfigClass()))
                throw new RuntimeException("Config class Error!!!");
        }

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding(Config.getENCODE());
        servletResponse.setContentType("text/html;charset=" + Config.getENCODE());

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        boolean[] isHandled = {false};

        handle(request, response, isHandled);

        if (isHandled[0])
            filterChain.doFilter(request, response);
    }


    @Override
    public void destroy() {

    }


    /**
     * 初始化映射表
     */
    private boolean initMaps() {
        try {
            controllerMap = new HashMap<String, Class>();
            methodMap = new HashMap<Class, Map<String, Action>>();

            PathUtil.util.scanController(Config.getClassRootPath(), controllerMap);
            PathUtil.util.scanMethod(controllerMap, methodMap);

            if (controllerMap.size() == 0) {
                return false;
            }

            return true;
        } catch (Exception e) {
            return false;
        }
    }


    private boolean initMore(Class config) {
        try {
            SimpleConfig simpleConfig = (SimpleConfig) config.newInstance();
            Config.setDevMode(simpleConfig.isDevMode());
            simpleConfig.configRender(BeetlRenderFactory.groupTemplate);
            simpleConfig.setGlobalInterceptor(globalInterceptors);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 初始化render
     */
    private boolean initRender() {
        try {
            BeetlRenderFactory.init();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * url处理
     */
    public void handle(HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
        String requestUri = request.getRequestURI();

        try {
            UrlAction urlAction = ActionFactory.translateUrl(requestUri, request.getMethod());

            if (Config.isDevMode()) {
                StringBuilder sb = new StringBuilder();
                sb.append("--------------------------------------------------------------------------------\nDebug\n")
                        .append("Action controller:\"").append(urlAction.getUrl0()).append("\" \n")
                        .append("Action method: \"").append(urlAction.getUrl1()).append("\" \n")
                        .append("--------------------------------------------------------------------------------");
                System.out.println(sb.toString());
            }

            Class controllerClass = controllerMap.get(urlAction.getUrl0());

            if (controllerClass == null) {
                isHandled[0] = true;
                return;
            }

            Action action = methodMap.get(controllerClass).get(urlAction.getUrl1());

            if (action == null) {
                isHandled[0] = true;
                return;
            }

            boolean methodFlag = false;

            for (ActionType type : action.getMethodType()) {
                if (type == urlAction.getActionType())
                    methodFlag = true;
            }

            if (!methodFlag)
                return;

            RenderFactory renderFactory = new RenderFactory(request, response);

            Controller controller = (Controller) controllerClass.newInstance();
            controller.init(request, response, renderFactory, urlAction);


            if (globalInterceptors.size() != 0) {
                boolean flag0 = true;
                for (Interceptor interceptor : globalInterceptors) {
                    flag0 = interceptor.invoke();
                }
                if (!flag0)
                    return;
            }


            boolean flag1 = false;

            Class[] interceptors = action.getInterceptor();
            for (Class inter : interceptors) {
                if (inter.getSuperclass().equals(Interceptor.class)) {
                    Interceptor interceptor = (Interceptor) inter.newInstance();
                    flag1 = interceptor.invoke();
                }
            }

            if (!flag1)
                return;


            action.getMethod().invoke(controller);//执行方法

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


}
